package com.jinmdz.fmis.api.admin.service;

import com.jinmdz.fmis.api.admin.model.car.CarIdData;
import com.jinmdz.fmis.api.admin.model.car.CarListData;
import com.jinmdz.fmis.api.admin.model.car.CarLoadData;
import com.jinmdz.fmis.api.admin.model.car.CarSaveData;
import com.jinmdz.fmis.api.api.model.common.IdVersionData;
import com.jinmdz.fmis.api.api.service.DictionaryService;
import com.jinmdz.fmis.api.api.service.UserService;
import com.jinmdz.fmis.api.base.BaseService;
import com.jinmdz.fmis.api.model.config.dictionary.OperationLogCode;
import com.jinmdz.fmis.api.model.system.UserItem;
import com.jinmdz.fmis.api.wrapper.DictionaryWrapper;
import com.jinmdz.fmis.api.wrapper.OperationWrapper;
import com.jinmdz.fmis.common.ext.StringBuilderExt;
import com.jinmdz.fmis.common.util.BeanUtil;
import com.jinmdz.fmis.common.util.DataUtil;
import com.jinmdz.fmis.core.base.BaseResult;
import com.jinmdz.fmis.core.constant.EDictCode;
import com.jinmdz.fmis.core.exception.ActionException;
import com.jinmdz.fmis.core.util.JacksonUtil;
import com.jinmdz.fmis.dao.admin.dao.CarDao;
import com.jinmdz.fmis.dao.admin.model.car.CarEditItem;
import com.jinmdz.fmis.dao.admin.model.car.CarListItem;
import com.jinmdz.fmis.dao.dao.ServiceItemDao;
import com.jinmdz.fmis.dao.model.dictionary.ServiceDictionaryRuleItem;
import com.jinmdz.fmis.mapper.entity.TransportCarEntity;
import com.jinmdz.fmis.mapper.mapper.TransportCarMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;

/**
 * 接运车辆Service
 *
 * @author LiCongLu
 * @date 2020-03-10 09:57
 */
@Service("carService")
public class CarService extends BaseService {

    @Resource
    private CarDao carDao;

    @Resource
    private DictionaryWrapper dictionaryWrapper;

    @Resource
    private TransportCarMapper transportCarMapper;

    @Resource
    private OperationWrapper operationWrapper;

    @Resource
    private OperationLogCode operationLogCode;

    @Resource
    private ServiceItemDao serviceItemDao;

    @Resource
    private DictionaryService dictionaryService;

    @Resource
    private UserService userService;

    /**
     * 加载接运车辆信息
     *
     * @param
     * @return
     * @author LiCongLu
     * @date 2020-03-10 11:12
     */
    public BaseResult<ArrayList<CarListData>> loadCarList() {
        ArrayList<CarListItem> loadItems = carDao.listCarList();
        // 设置字典文本
        dictionaryWrapper.resetDataText(loadItems);

        // 加载服务规则
        String dictCode = EDictCode.TRANSPORT_CAR_TYPE.getCode();
        ArrayList<ServiceDictionaryRuleItem> ruleAllItems = serviceItemDao.listServiceDictionaryRuleByDictCode(dictCode, "");
        // 返回数据
        ArrayList<CarListData> dataList = BeanUtil.copy2List(loadItems, CarListData.class);
        for (CarListData listData : dataList) {
            ArrayList<ServiceDictionaryRuleItem> ruleItems = new ArrayList<>();
            ruleAllItems.forEach(ruleItem -> {
                // 判断数据结构
                if (DataUtil.equals(ruleItem.getDataCode(), listData.getCarTypeCode())) {
                    ruleItems.add(ruleItem);
                }
            });
            listData.setRuleItems(ruleItems);
        }

        return successList(dataList);
    }

    /**
     * 加载接运车辆信息
     *
     * @param data 车辆主键
     * @return
     * @author LiCongLu
     * @date 2020-03-10 09:59
     */
    public BaseResult<CarLoadData> loadCarWithId(CarIdData data) {

        // 加载数据
        CarLoadData loadData = new CarLoadData();

        // 加载数据
        if (DataUtil.valid(data.getId())) {
            Integer loadId = data.getId();
            // 查询信息
            CarEditItem loadItem = carDao.getCarEditById(loadId);
            if (DataUtil.isNull(loadItem) || DataUtil.isNull(loadItem.getId(), loadItem.getVersion())) {
                return failure("主键错误，不存在此接运车辆信息");
            }
            loadData.setCar(BeanUtil.copy2Bean(loadItem, new CarSaveData()));
        }

        // 加载字典数据
        loadData.setDicts(dictionaryService.loadDictionaryMap(data.getDictTypeCodes()));

        // 加载服务规则
        String dictCode = EDictCode.TRANSPORT_CAR_TYPE.getCode();
        loadData.setRuleItems(serviceItemDao.listServiceDictionaryRuleByDictCode(dictCode, ""));

        // 加载用户数据
        if (DataUtil.valid(data.getUserRoleCodes())) {
            loadData.setUsers(userService.loadRoleUserMap(data.getUserRoleCodes()));
        }

        // 返回响应结果
        return successData(loadData);
    }

    /**
     * 保存接运车辆信息
     *
     * @param userItem 当前帐号
     * @param data     请求数据
     * @return
     * @author LiCongLu
     * @date 2020-03-10 11:37
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult saveCar(UserItem userItem, CarSaveData data) throws ActionException {
        Integer id = data.getId();
        // 主键不为空
        if (DataUtil.valid(id)) {
            updateCar(userItem, data);
        } else {
            id = insertCar(userItem, data);
        }
        return success("保存成功");
    }

    /**
     * 插入接运车辆信息
     *
     * @param userItem 当前帐号
     * @param data     请求数据
     * @return
     * @author LiCongLu
     * @date 2020-03-10 11:39
     */
    private Integer insertCar(UserItem userItem, CarSaveData data) throws ActionException {
        // 创建实体
        TransportCarEntity entity = getEntity(userItem, TransportCarEntity.class);

        // 覆盖数据
        BeanUtil.copy2Bean(data, entity);

        // 对车辆信息进行判断处理
        checkCarValue(entity);

        // 新增接运车辆信息
        transportCarMapper.insertTransportCar(entity);
        // 判断保存车辆信息结果
        if (DataUtil.invalid(entity.getId())) {
            throw exception("保存接运车辆信息失败");
        }

        // 添加操作日志
        saveCarLog(userItem, operationLogCode.getInsert(), data, null, entity);
        return entity.getId();
    }

    /**
     * 验证处理车辆信息
     *
     * @param entity 车辆接运信息
     * @return
     * @author LiCongLu
     * @date 2020-03-10 11:48
     */
    private void checkCarValue(TransportCarEntity entity) throws ActionException {
        // 判断车牌编号是否存在
        if (DataUtil.invalid(entity.getCarCode())) {
            entity.setCarCode(entity.getCarNo());
        }

        // 判断车辆里程价格
        if (DataUtil.isNull(entity.getTransportPrice())) {
            entity.setTransportPrice(new BigDecimal(0));
        }

        // 判断禁用状态
        if (DataUtil.isNull(entity.getDisableState())) {
            entity.setDisableState(0);
        }

        // 判断排序值
        if (DataUtil.isNull(entity.getSort())) {
            entity.setSort(0);
        }

        // 判断车辆编号的重复性
        Integer carCodeId = carDao.getCarIdByCarCode(entity.getId(), entity.getCarCode());
        if (DataUtil.valid(carCodeId)) {
            throw exception("存在重复的车辆编号");
        }

        // 判断车牌号的重复性
        Integer carNoId = carDao.getCarIdByCarNo(entity.getId(), entity.getCarNo());
        if (DataUtil.valid(carNoId)) {
            throw exception("存在重复的车牌号");
        }
    }

    /**
     * 添加接运修改记录
     *
     * @param userItem    当前帐号
     * @param logTypeCode 操作日志值
     * @param data        请求数据
     * @param oldValue    旧数据
     * @param entity      保存实体
     * @return
     * @author LiCongLu
     * @date 2020-03-10 14:04
     */
    private void saveCarLog(UserItem userItem, Integer logTypeCode, CarSaveData data, String oldValue, TransportCarEntity entity) throws ActionException {
        // 操作日志字符串
        StringBuilderExt builder = new StringBuilderExt();
        builder.format("保存接运车辆信息，车辆类型[{0}][{1}]，车辆归属类型[{2}][{3}]，车辆编号[{4}]，车牌号[{5}]，里程单价[{6}]，禁用状态值[{7}]，关联司机[{8}]，操作人员[{9}]"
                , String.valueOf(data.getCarTypeCode()), dictionaryWrapper.getDataText(EDictCode.TRANSPORT_CAR_TYPE, data.getCarTypeCode())
                , String.valueOf(data.getCarBelongCode()), dictionaryWrapper.getDataText(EDictCode.CAR_BELONG, data.getCarBelongCode())
                , data.getCarCode(), data.getCarNo(), String.valueOf(data.getTransportPrice()), String.valueOf(data.getDisableState())
                , String.valueOf(data.getDriverUserId()), userItem.getFullName());

        // 添加日志
        operationWrapper.operationLog(userItem, logTypeCode, builder.toString(), JacksonUtil.obj2Json(data), oldValue, JacksonUtil.obj2Json(entity));
    }

    /**
     * 更新接运车辆信息
     *
     * @param userItem 当前帐号
     * @param data     请求数据
     * @return
     * @author LiCongLu
     * @date 2020-03-10 11:40
     */
    private void updateCar(UserItem userItem, CarSaveData data) throws ActionException {
        // 验证主键和数据版本是否存在
        if (DataUtil.isNull(data.getId(), data.getVersion())) {
            throw exception("请求车辆主键与车辆版本号不能为空");
        }

        // 通过主键获取接运车辆信息
        TransportCarEntity entity = transportCarMapper.getTransportCarById(data.getId());
        if (DataUtil.isNull(entity) || DataUtil.isNull(entity.getId(), entity.getVersion())) {
            throw exception("车辆主键错误，不存在此车辆信息");
        }

        // 验证信息版本
        if (!DataUtil.equals(data.getVersion(), entity.getVersion())) {
            throw exception(versionError("车辆信息"));
        }

        // 记录旧数据
        String oldValue = JacksonUtil.obj2Json(entity);

        // 覆盖数据
        BeanUtil.copy2Bean(data, entity);

        // 对车辆信息进行判断处理
        checkCarValue(entity);

        // 更新接运车辆信息
        transportCarMapper.updateTransportCar(entity);

        // 添加操作日志
        saveCarLog(userItem, operationLogCode.getUpdate(), data, oldValue, entity);
    }

    /**
     * 从transport_car表中删除指定id的接运车辆信息记录
     *
     * @param userItem 当前帐号
     * @param data     主键和版本号
     * @return
     * @author LiCongLu
     * @date 2020-03-10 13:33
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult deleteCarWithId(UserItem userItem, ArrayList<IdVersionData> data) throws ActionException {
        // 判断删除主键集合是否存在
        if (DataUtil.invalid(data)) {
            throw exception("不存在要删除的车辆信息");
        }

        // 验证主键是否重复
        if (data.size() != getRepeatIdSize(data)) {
            throw exception("车辆主键存在重复");
        }

        // 记录车辆信息集合
        ArrayList<CarEditItem> loadItems = new ArrayList<>();

        // 遍历查询进行删除
        for (IdVersionData idData : data) {
            // 通过主键查询车辆信息
            CarEditItem loadItem = carDao.getCarEditById(idData.getId());
            if (DataUtil.isNull(loadItem) || DataUtil.isNull(loadItem.getId(), loadItem.getVersion())) {
                throw exception("主键错误，不存在此车辆信息");
            }

            // 验证车辆信息版本
            if (!DataUtil.equals(loadItem.getVersion(), idData.getVersion())) {
                throw exception(versionError("车辆信息"));
            }

            // 删除车辆信息
            transportCarMapper.deletedForTransportCar(loadItem.getId(), userItem.getId(), loadItem.getVersion());

            // 记录车辆信息
            loadItems.add(loadItem);
        }

        // 添加操作日志信息
        deleteCarLog(userItem, operationLogCode.getDelete(), data, loadItems);

        return success("删除成功");
    }

    /**
     * 添加修改记录
     *
     * @param userItem    当前帐号
     * @param logTypeCode 操作日志值
     * @param data        请求数据
     * @param loadItems   删除信息实体
     * @return
     * @author LiCongLu
     * @date 2020-03-10 14:04
     */
    private void deleteCarLog(UserItem userItem, Integer logTypeCode, ArrayList<IdVersionData> data, ArrayList<CarEditItem> loadItems) throws ActionException {
        // 操作日志字符串
        StringBuilderExt builder = new StringBuilderExt();
        builder.format("删除接运车辆信息，操作人员[{1}]", userItem.getFullName());
        // 添加日志
        operationWrapper.operationLog(userItem, logTypeCode, builder.toString(), JacksonUtil.obj2Json(data), JacksonUtil.obj2Json(loadItems), null);
    }
}
